﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Constructor.Controls;
using Constructor.Frames;

namespace Constructor
{
    public class External
    {
        public const bool SimpleMLO = true;

        private static bool _ExitMLO = false;
        public static bool ExitMLO
        {
            get { return _ExitMLO; }
            set { _ExitMLO = ExitMLO; }
        }

        public static FrameConstructor constructor;
        public static Images images;
        public static List<Frame> frames;
        public static DataSet ds;
        public static Dictionary<string, Frame> Parents = new Dictionary<string, Frame>();
        public static ExemplarConstructor exemplars;
        public static ObjectExplorer explorer;
        public static Frame SearchFrame(string id)
        {
            foreach (Frame f in frames)
                if (f.ID == id || f.Name == id) return f;
            return null;
        }
        public static Frame SearchFrameIn(List<Frame> frames, string id)
        {
            foreach (Frame f in frames)
                if (f.ID == id || f.Name == id) return f;
            return null;
        }
        public static string GetNameExemplarFrame(Frame prototype)
        {
            int i = 1;
            while (SearchFrameIn(MLO.MLOSource.Exemplars, prototype.Name + i.ToString()) != null)
                i++;
            return prototype.Name + i.ToString();
        }
        public static void AddSlotToExem(Frame exem, Slot slot)
        {
            if (slot.Type == CommonLib.SlotType.Regular || slot.Type == CommonLib.SlotType.SubFrame)
            {
                Slot s = slot.Clone(exem);
                //s.ID = Guid.NewGuid().ToString();
                if (s.Domain != null && s.Domain.Type == CommonLib.DomainType.Number && s.Inherit == CommonLib.TypeInherit.Range)
                {
                    MinMax range = new MinMax(s.Default.ToString());
                    if (range.valid)
                        s.Default = range.Min;
                }
                exem.Slots.Add(s);
            }
        }
        public static Frame GetExemplarByPrototype(Frame prototype)
        {
            if (prototype == null) return null;
            if (prototype.Type != CommonLib.FrameType.Prototype) return null;
            Frame exem = new Frame(GetNameExemplarFrame(prototype));
            exem.Type = CommonLib.FrameType.Exemplar;
            foreach (Slot slot in prototype.AllSlots)
                AddSlotToExem(exem, slot);
            MLO.MLOSource.Exemplars.Add(exem);
            Parents.Add(exem.ID, prototype);
            return exem;
        }
        public static NewItem GetItem(string value)
        {
            int cnt = value.Split('.').Length;
            Frame f = null;
            if (cnt > 0)
                f = External.SearchFrame(value.Split('.')[0]);
            Slot s = null;
            NewItem result = null;
            if (f != null)
            {
                result = new NewItem(f.ID, null);
                for (int i = 1; i < cnt; i++)
                {
                    if (f != null)
                        s = f.SearchInAllSlot(value.Split('.')[i]);
                    if (s != null)
                    {
                        result.Add(s.ID);
                        f = s.Subframe;
                    }
                }
                result.Content = s;
            }
            return result;
        }
        public static bool Relatives(string frame1, string frame2)
        {
            if (frame1 == frame2) return true;
            Frame frame = SearchFrame(frame1);
            if (frame != null)
            {
                Frame parent = frame.ParentFrame;
                while (parent != null)
                {
                    if (parent.ID == frame2) return true;
                    parent = parent.ParentFrame;
                }
            }
            frame = SearchFrame(frame2);
            if (frame != null)
            {
                Frame parent = frame.ParentFrame;
                while (parent != null)
                {
                    if (parent.ID == frame1) return true;
                    parent = parent.ParentFrame;
                }
            }
            return false;
        }
        public static bool CompareSlots(Slot parent, Slot child)
        {
            if (parent.Type != child.Type) return false;
            if (parent.Type == CommonLib.SlotType.Regular) return parent.DomainID == child.DomainID;
            else if (parent.Type == CommonLib.SlotType.SubFrame)
                return Relatives(parent.Subframe.ID, child.Subframe.ID);
            return true;
        }
    }

    struct MinMax
    {
        public MinMax(string value)
        {
            string[] splitResult = value.Split(new string[] { ".." }, 2, StringSplitOptions.None);
            valid = false;
            Min = 0;
            Max = 0;
            switch (splitResult.Length)
            {
                case 1:
                    valid = int.TryParse(splitResult[0], out Min);
                    if (valid)
                        Max = Min;
                    break;
                case 2:
                    valid = int.TryParse(splitResult[0], out Min)
                        && int.TryParse(splitResult[1], out Max)
                        && Max >= Min;
                    break;
            }
        }
        public int Min;
        public int Max;
        public bool valid;
    }
}
